#include "stdafx.h"
#include "./glTrace.h"
#include "./glPainter.h"
#include "./glPict.h"
#include "./glApp.h"
#include "./glCanvas.h"

namespace GLES
{
    template <typename T>
    struct Point2D
    {
    public:
        typedef T Type;
        const static int Dimension = 2;
        Point2D(T _x,T _y):x(_x),y(_y){}
    public:
        T x;
        T y;
    };
    template <typename T>
    struct Point3D
    {
    public:
        typedef T Type;
        const static int Dimension = 3;
        Point3D(T _x,T _y,T _z = 0):x(_x),y(_y),z(_z){}
    public:
        T x;
        T y;
        T z;
    };

    template <typename T>
    struct Rect
    {
    public:
        typedef T type;

        Rect(T _x,T _y,T _w,T _h):x(_x),y(_y),w(_w),h(_h){}
    public:
        T x;
        T y;
        T w;
        T h;
    };

    #define PointD Point2D
    typedef PointD<int> iPoint;
    typedef PointD<float> fPoint;
    typedef PointD<unsigned int> uPoint;

    typedef Rect<int> iRect;
    typedef Rect<float> fRect;
    typedef Rect<unsigned int> uRect;

    //class Color
    //{
    //public:
    //    const static int Dimension = 4;
    //    const static int GLType = GL_UNSIGNED_BYTE;
    //    typedef GLbyte Type;
    //    typedef unsigned char u8;
    //    Color(){}
    //    Color(u8 _r,u8 _g,u8 _b,u8 _a = 255):r(_r),g(_g),b(_b),a(_a){}
    //public:
    //    GLbyte r;
    //    GLbyte g;
    //    GLbyte b;
    //    GLbyte a;
    //};

    
    static Color lineColor;
    static Color brushColor;

    template <typename T>
    int GL_(){return GL_FLOAT;}

    typedef Rect<GLfloat> fRect;
    typedef Rect<GLfixed> xRect;

    typedef PointD<GLfloat> fPoint;

    typedef PointD<GLfixed> xPoint;

    typedef PointD<GLfloat> fCoord;



    //////////////////////////////////////////////////////////////////////////

 //   void DrawRect(GLES::fRect rect)
 //   {
 //       GLES::fPoint x1(rect.x,rect.y),x2(rect.x + rect.w,rect.y),x3(rect.x + rect.w,rect.y + rect.h),x4(rect.x,rect.y + rect.h);
 //       GLES::fPoint vertices[5] = {x1,x2,x3,x4,x1};
 //       DrawLine(vertices,5);
 //   }

	//void DrawRect( fRect rect,Color color )
	//{
	//	GLES::fPoint x1(rect.x,rect.y),x2(rect.x + rect.w,rect.y),x3(rect.x + rect.w,rect.y + rect.h),x4(rect.x,rect.y + rect.h);
	//	GLES::fPoint vertices[5] = {x1,x2,x3,x4,x1};
	//	DrawLine(vertices,5,color);
	//}

	void BlendRect(GLES::fRect rect,Color color)
	{
		GLfloat vertices[] =
		{
			rect.x,rect.y,
			rect.x ,rect.y + rect.h,
			rect.x + rect.w,rect.y ,
			rect.x + rect.w,rect.y + rect.h
		};

		Color colors[] = {color,color,color,color};
		glEnable(GL_BLEND);
		glBlendFunc(GL_ZERO , GL_SRC_COLOR);

		glDisable(GL_TEXTURE_2D);

		glDisableClientState(GL_TEXTURE_COORD_ARRAY);

		glEnableClientState(GL_COLOR_ARRAY);
		glEnableClientState(GL_VERTEX_ARRAY);

		glVertexPointer(2, GL_FLOAT, 0, vertices);

		glColorPointer(4, GL_UNSIGNED_BYTE, 0, colors);

		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
	}

    void FillRect(GLES::fRect rect,Color color)
    {
        GLfloat vertices[] =
		{
			rect.x,rect.y,
			rect.x ,rect.y + rect.h,
			rect.x + rect.w,rect.y ,
			rect.x + rect.w,rect.y + rect.h
		};

		Color colors[] = {color,color,color,color};
		glDisable(GL_BLEND);
		glDisable(GL_COLOR_LOGIC_OP);
		glDisable(GL_TEXTURE_2D);

        glDisableClientState(GL_TEXTURE_COORD_ARRAY);

		glEnableClientState(GL_COLOR_ARRAY);
		glEnableClientState(GL_VERTEX_ARRAY);

		glVertexPointer(2, GL_FLOAT, 0, vertices);

        glColorPointer(4, GL_UNSIGNED_BYTE, 0, colors);

        glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
        
    }

}
namespace GLES
{

	void Painter::drawPoint(PointI* point,int numb)
	{
		glDisable(GL_TEXTURE_2D);
		glDisableClientState(GL_TEXTURE_COORD_ARRAY);
		glDisableClientState(GL_COLOR_ARRAY);

		glVertexPointer(2, GL_FLOAT, 0, point);
		glDrawArrays(GL_POINTS, 0, numb);

		// restore default state
		glEnableClientState(GL_COLOR_ARRAY);
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);
		glEnable(GL_TEXTURE_2D);
	};

	Void Painter::drawLine( PointI& start,PointI& end )
	{

		GLES::fPoint vertices[2] = {GLES::fPoint(start.x,start.y),GLES::fPoint(end.x,end.y)};

		glDisable(GL_TEXTURE_2D);
		glDisableClientState(GL_TEXTURE_COORD_ARRAY);
		glEnableClientState(GL_VERTEX_ARRAY);

		glVertexPointer(3, GL_FLOAT, 0, vertices);	
		glDrawArrays(GL_LINE_STRIP, 0, 1);

		glEnableClientState(GL_COLOR_ARRAY);
		glEnable(GL_TEXTURE_2D);
	}

	Void Painter::drawPict( RectI& dstRect,Pict* iPict,RectI* srcRect )
	{
		
		Float xc = _screenSize.w / 2;
		float yc = _screenSize.h / 2;

		GLfloat x1 = (dstRect.x1 - xc) / xc;
		GLfloat y1 = -(dstRect.y1 - yc) / yc;
		GLfloat x2 = (dstRect.x2 - xc) / xc;
		GLfloat y2 = -(dstRect.y2 - yc) / yc;

		GLfloat vertex[12]={x1,y1,0,
							x1,y2,0,
							x2,y2,0,
							x2,y1,0
				};

		const GLfloat squareTextureCoords[] = {
			0, 0,       // bottom left
			0, 1,       // top left
			1, 1,       // bottom right
			1, 0        // top right
		};
		glBindTexture(GL_TEXTURE_2D, iPict->getTexture());

		glColor4ub(255,255,255,255);

		glEnable (GL_BLEND);

		glBlendFunc(GL_SRC_ALPHA , GL_ONE_MINUS_SRC_ALPHA);

		glEnableClientState(GL_VERTEX_ARRAY);
		glDisableClientState(GL_COLOR_ARRAY);
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);
		
		glEnable(GL_TEXTURE_2D);

		glVertexPointer(3, GL_FLOAT, 0, vertex);
		glTexCoordPointer(2, GL_FLOAT, 0, squareTextureCoords);

		glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
		glDisable(GL_BLEND);

	}

	Void Painter::setPenColor( Color color )
	{
	}

	Painter::Painter()
	{
		GLES::lineColor = GLES::Color(0,0,0,255);
		GLES::brushColor = GLES::Color(0,0,0,255);
		//m_Print3D.SetTextures(0,20,20,false);
	}

	Bool Painter::begin()
    {
		do 
		{
			eglReleaseTexImage(GLES::getContext()->m_eglDisplay, _canvas->getSurface(), EGL_BACK_BUFFER);
			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_NEAREST);
			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
			//////////////////////////////////////////////////////////////////////////

			//E_Bre0ak_If(eglReleaseTexImage(GLES::getContext()->m_eglDisplay, _canvas->getSurface(), EGL_BACK_BUFFER) 
			//	== EGL_FALSE);

			//E_Break_If(eglMakeCurrent(GLES::getContext()->m_eglDisplay, _canvas->getSurface(), _canvas->getSurface(), GLES::getContext()->m_eglContext)
			//	== EGL_FALSE);

			glClearColorx(0, 0, 0x10000, 0);
			glClear(GL_COLOR_BUFFER_BIT);

			return true;
		} while (0);

		xWarning1("Painter::begin() error(%x)",glGetError());
		return false;
	}

	Void Painter::end()
	{
		if(_canvas && _canvas->getPict())
		{
			glBindTexture(GL_TEXTURE_2D, _canvas->getPict()->getTexture());
			eglBindTexImage(GLES::getContext()->m_eglDisplay, _canvas->getSurface(), EGL_BACK_BUFFER);
		}
		return;
	}

//	Void Painter::present( Pict* pict )
//	{
//		do 
//		{
//			//////////////////////////////////////////////////////////////////////////
//
//			glBindTexture(GL_TEXTURE_2D, pict->getTexture());
//
//			E_Break_If(!eglBindTexImage(GLES::getContext()->m_eglDisplay, mCanvas->getSurface(), EGL_BACK_BUFFER));
//
//			E_Break_If(!eglMakeCurrent(GLES::getContext()->m_eglDisplay, GLES::getContext()->m_eglSurface,GLES::getContext()->m_eglSurface, GLES::getContext()->m_eglContext));
//
//			int Width,Height;
//
//			eglQuerySurface(GLES::getContext()->m_eglDisplay, GLES::getContext()->m_eglSurface,EGL_WIDTH,  (EGLint*)&Width);
//
//			eglQuerySurface(GLES::getContext()->m_eglDisplay, GLES::getContext()->m_eglSurface,EGL_HEIGHT, (EGLint*)&Height);
//
//			int N_PLANE_W = Width;
//			int N_PLANE_H = Height;
//
//			GLbyte colors[] = {
//				0,255,0,0,
//				0,0,255,0,
//				0,255,255,0,
//				255,0,255,255
//			};
//
//			
//			glClearColorx(0x10000, 0, 0, 0);
//
//			glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
//			
//#define  BORDER_DLTA 5.0f
//
//			GLfloat vertex[]={
//				-Width/2 + BORDER_DLTA,-Height/2 + BORDER_DLTA,0,
//				-Width/2 + BORDER_DLTA, Height/2 - BORDER_DLTA,0,
//				Width/2  - BORDER_DLTA,-Height/2 + BORDER_DLTA,0,
//				Width/2  - BORDER_DLTA, Height/2 - BORDER_DLTA,0};
//
//			GLfloat rationW = (GLfloat)Width/(GLfloat)pict->getSize().w;
//			GLfloat rationH = (GLfloat)Height/(GLfloat)pict->getSize().h;
//
//			const GLfloat squareTextureCoords[] = {
//					0, 0,				// bottom left
//					0, rationH,			// top left
//					rationW, 0,			// bottom right
//					rationW,rationH      // top right
//
//				};
//				glColor4ub(255,255,255,0);
//				glDisable(GL_BLEND);
//				glEnableClientState(GL_VERTEX_ARRAY);
//				glEnableClientState(GL_TEXTURE_COORD_ARRAY);
//				glDisableClientState(GL_COLOR_ARRAY);
//				glEnable(GL_TEXTURE_2D);
//
//				glVertexPointer(3, GL_FLOAT, 0, vertex);
//				glTexCoordPointer(2, GL_FLOAT, 0, squareTextureCoords);
//				glColorPointer(4,GL_UNSIGNED_BYTE,0,colors);
//
//				glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
//
//				E_Break_If(eglSwapBuffers (GLES::getContext()->m_eglDisplay, GLES::getContext()->m_eglSurface)
//					== EGL_FALSE);
//				return;
//
//		} while (0);
//		xAssert(vNull);
//		return;
//	}

	Void Painter::fillRect( RectI& rect )
	{
        //FillRect(GLES::fRect(rect.x1,rect.y,rect.w,rect.h));
	}

	Void Painter::setBrushColor( Color color )
	{
		GLES::brushColor = GLES::Color(color.r,color.g,color.b,color.a);
	}

	Bool Painter::attachPict( Pict* iPict )
	{
		return false;
	}


	Void Painter::drawRect( RectI& rect )
	{
        //return GLES::DrawRect(GLES::fRect(rect.x,rect.y,rect.w,rect.h));
	}


	Void Painter::fillRect( RectI& rect,Color color )
	{

		//return GLES::FillRect(GLES::fRect(rect.x,rect.y,rect.w,rect.h),GLES::Color(color.r,color.g,color.b,color.a));
	}

	GLES::Void Painter::blendRect( RectI& rect,Color color )
	{
		//return GLES::BlendRect(GLES::fRect(rect.x,rect.y,rect.w,rect.h),GLES::Color(color.r,color.g,color.b,color.a));
	}

	Void Painter::drawRect( RectI& rect,Color color )
	{
		//GL::fPoint x1(rect.x,rect.y),x2(rect.x + rect.w,rect.y),x3(rect.x + rect.w,rect.y + rect.h),x4(rect.x,rect.y + rect.h);
		GLfloat vertices[] =
		{
			rect.x1,rect.y1,
			rect.x1,rect.y2,
			rect.x2,rect.y2,
			rect.x2,rect.y1
		};
		//Color c(0,0,0,125);
		//Color colors[5] = {c,c,c,c,c};

		glEnable (GL_BLEND);

		glDisableClientState(GL_TEXTURE_COORD_ARRAY);
		glDisable(GL_TEXTURE_2D);

		glVertexPointer(2, GL_FLOAT, 0, vertices);
		//glColorPointer(Color::Dimension, Color::GLType, 0, colors);

		//glBlendFunc(GL_ONE_MINUS_DST_ALPHA,GL_SRC_ALPHA );

		glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);

		//if( newBlend )
		//    glBlendFunc(CC_BLEND_SRC, CC_BLEND_DST);

		// restore default GL state
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);
		glEnable(GL_TEXTURE_2D);
	}

	Painter::~Painter()
	{
		//m_Print3D.ReleaseTextures();
	}	

	GLES::Bool Painter::attachCanvas( Canvas* canvas )
	{
		_canvas = canvas;
		return eglMakeCurrent(GLES::getContext()->m_eglDisplay, canvas->getSurface(), canvas->getSurface(), GLES::getContext()->m_eglContext);
	}

	GLES::Void Painter::detachCanvas()
	{
		_canvas = NULL;
		eglMakeCurrent(GLES::getContext()->m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
		return ;
	}

	GLES::Void Painter::present()
	{
		eglSwapBuffers(GLES::getContext()->m_eglDisplay, _canvas->getSurface());
	}
}
